/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package game.client;

import game.server.Gamer;
import game.server.IGameServer;
import java.awt.EventQueue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;

/**
 *
 * @author RERIR
 */
public class TestGameClient {
    private static String DEFAULT_SERVER = "localhost";
    
    private InetAddress server;
    private DatagramSocket socket;
    private DatagramPacket packet;
    private byte[] buffer;
    private JFrame frame;
//    private ClientForm listener;
    private Gamer gamer;
    private GameField field;
    private Socket client;
    private ObjectInputStream in;
    private ObjectOutputStream out;
    

    public TestGameClient() throws SocketException, UnknownHostException {
        socket = new DatagramSocket();
        buffer = new byte[IGameServer.BUFFER_SIZE];
        packet = new DatagramPacket(buffer, buffer.length);
        server = InetAddress.getByName(DEFAULT_SERVER);
        
        // open User frame here
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                initFrame();
            }
        });
    }

    public TestGameClient(String host) throws UnknownHostException, SocketException {
        this();
        server = InetAddress.getByName(host);
    }

    public boolean initGame(String serverHost) {
        try {
            client = new Socket(serverHost, IGameServer.SERVER_TCP_PORT);
            out = new ObjectOutputStream(client.getOutputStream());
            in = new ObjectInputStream(client.getInputStream());
            

        } catch (UnknownHostException ex) {
            System.out.println("Err UnknownHost: "+ex.getMessage());
            return false;
        } catch (IOException ex) {
             System.out.println("Err IO: "+ex.getMessage());
             return false;
        }
        return true;
    }
    
    public int move(int move) {
        Object obj = null;;
        try {
            out.writeObject(new Integer(move));
            obj = in.readObject();
 
         } catch (IOException ex) {
            System.out.println("Err IO: "+ex.getMessage());
         } catch (ClassNotFoundException ex) {
            System.out.println("Err CastObject: "+ex.getMessage());
       }
        return (obj != null && obj instanceof Integer) ? (Integer)obj : -1;
    }
    
    public int getFirstMove() {
        Object obj = null;;
        try {
             obj = in.readObject();
 
         } catch (IOException ex) {
            System.out.println("Err IO: "+ex.getMessage());
         } catch (ClassNotFoundException ex) {
            System.out.println("Err CastObject: "+ex.getMessage());
       }
        return (obj != null && obj instanceof Integer) ? (Integer)obj : -1;
    }
    
    public boolean stopGame() {
        try {
            in.close();
            out.close();
            client.close();
            return true;
        } catch (IOException ex) {
            System.out.println("Err IO: "+ex.getMessage());
            return false;
        }
    }
    

    public void run(String host) {
        Gamer[] ag = getList();
        System.out.println("newGame : " + newGame("test"));
        System.out.println("joinGame: " + joinGame("demo", 1));
        initGame(host);
//        getFirstMove();
        move(1);
        move(2);
//        initGame(host); //TODO pass real host name
        
    }
    
    private class MoveRobot implements MoveListener {
        @Override
        public void MovePerformed(int move) {
            System.out.println("Move: " + move);
            freeMove.remove(freeMove.indexOf(move));
            if (freeMove.size()>0) {
                Random rnd = new Random();
                int nextMove = freeMove.get(rnd.nextInt(freeMove.size()));
                field.moveAnotherSide(nextMove);
                freeMove.remove(freeMove.indexOf(nextMove));
            }
            else {
                String path = "";
                for (int i = 0; i < GameField.SIZE_FIELD*GameField.SIZE_FIELD; i++) path += "1";
                field.highlightPath(path);
            }
        }

   
        public MoveRobot() {
            for (int i = 0; i < GameField.SIZE_FIELD*GameField.SIZE_FIELD; i++) freeMove.add(i);
        }
        
        
        private List<Integer> freeMove = new LinkedList<>();
    }


    private void initFrame() {
        MoveRobot listener = new MoveRobot();
        field = new GameField(IGameServer.PLUS, listener);

//        listener.setField(field);
        frame = new JFrame("Крестики - Нолики");
        frame.add(field);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    private Gamer[] getList() {
        Object obj = sendCommand("list");
        
        if (obj != null && obj instanceof Gamer[]) {
            printList((Gamer[])obj);
            return (Gamer[])obj;
        }
        return null;
    }

    private void printList(Gamer[] gamer) {
        System.out.println("Gamer list:\n---------------------------------------------");
        for (Gamer g: gamer) System.out.println(g);
    }
    
    public boolean newGame(String login) {
        Object obj = sendCommand("new " + login);
        
        if (obj != null && obj instanceof Integer) {
            gamer = new Gamer(login, null);
            gamer.setGameId((Integer)obj);
            return true;
        }
        return false;
    }
    public boolean joinGame(String login, int idGame) {
        Object obj = sendCommand("join " + login + " " + idGame);
        
        if (obj != null && obj instanceof String) {
            if (((String)obj).isEmpty()) {
                return false;
            }
            gamer = new Gamer(login, null);
            gamer.setGameId(idGame);
            return true;
        }
        return false;
    }
        
    private Object sendCommand(String command) {
        packet.setData(command.getBytes());
        packet.setAddress(server);
        packet.setPort(IGameServer.SERVER_PORT);
        try {
            socket.send(packet);
            packet.setData(new byte[IGameServer.BUFFER_SIZE]);
            socket.receive(packet);
            
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
            return null;
        }
        ByteArrayInputStream bIn = new ByteArrayInputStream(packet.getData(), packet.getOffset(), packet.getLength());

        Object obj;
        try {
            ObjectInputStream oIn = new ObjectInputStream(bIn);
            obj = oIn.readObject();
        } catch (IOException ex) {
            System.out.println("Err1: "+ex.getMessage());
            return null;
        } catch (ClassNotFoundException ex) {
            System.out.println("Err2: "+ex.getMessage());
            return null;
        }
        return obj;
   }
    
}
